package lp2.projeto.horario;

import java.io.Serializable;
import java.util.Calendar;

/**
 * Representa um intervalo de tempo
 */
public class Intervalo implements Comparable<Horario>, Serializable {

	private static final long serialVersionUID = -3041808233319144159L;
	private Horario inicio, fim;
	
	/**
	 * Construtor do Intervalo que usa o inicio e fim do intervalo
	 * @param inicio Inicio do intervalo
	 * @param fim Fim do intervalo
	 * @throws IllegalArgumentException Caso o fim do intervalo anteceda (ou se iguale) ao inicio do intervalo
	 */
	public Intervalo(Horario inicio, Horario fim) throws IllegalArgumentException {
		if (inicio.compareTo(fim) >= 0)
			throw new IllegalArgumentException("O horario de inicio deve vir antes do fim");
		this.inicio = inicio;
		this.fim = fim;
	}
	
	/**
	 * Construtor do Intervalo que usa o inicio e a duracao do intervalo
	 * @param inicio Inicio do intervalo
	 * @param fim Fim do intervlao, medido em minutos
	 * @throws IllegalArgumentException Caso a duracao seja nao-positiva
	 */
	public Intervalo(Horario inicio, int duracao) throws IllegalArgumentException {
		if (duracao <= 0)
			throw new IllegalArgumentException("A duracao deve ser positiva");
		this.inicio = inicio;
		
		Calendar calendar = inicio.toCalendar();
		calendar.add(Calendar.MINUTE, duracao);
		this.fim = new Horario(calendar);
	}
	
	/**
	 * @return O inicio do intervalo
	 */
	public Horario getInicio() {
		return inicio;
	}
	
	/**
	 * @return O fim do intervalo
	 */
	public Horario getFim() {
		return fim;
	}
	
	/**
	 * Retorna a duracao do intervalo de tempo, medida em minutos
	 * @return a duracao
	 */
	public int getDuracao() {
		long diferenca_millis = fim.toCalendar().getTimeInMillis() - inicio.toCalendar().getTimeInMillis();
		return (int)((diferenca_millis+(1000L*60L/2L))/(1000L*60L));
	}
	
	/**
	 * Confere colisao de intervalos de tempo
	 * 
	 * Nota: Se dois intervalos apenas se tocam nas extremidades,
	 * entao eles nao colidem.
	 * 
	 * @param outro Outro intervalo
	 * @return Se houve colisao
	 */
	public boolean colideCom(Intervalo outro) {
		return !(fim.compareTo(outro.getInicio()) <= 0 || inicio.compareTo(outro.getFim()) >= 0);
	}
	
	/**
	 * Retorna uma representacao em String to objeto
	 * @return A representacao
	 */
	@Override public String toString() {
		return "(" + inicio + ", " + fim + ")"; 
	}

	/**
	 * Compara o horario de inicio do evento com um determinado horario
	 * @return >0 se o evento for futuro com relacao ao horario, <0 se for passado, 0 se o inicio do intervalo coincidir com o horario
	 */
	@Override
	public int compareTo(Horario horario) {
		return inicio.compareTo(horario);
	}
}
